3f870808zS6T6iFhqYPGelroZlVfGQ tools/misc/xen_cpuperf.c
405eedf6_nnNhFQ1I85lhCkLK6jFGA tools/misc/xencons
40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/misc/xend
+4107986eMWVdBoz4tXYoOscpN_BCYg tools/misc/xensv
4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops.py
40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
40c9c468icGyC5RAF1bRKsCXPDCvsA tools/python/Makefile
40dc4076pVeE1kEEWzcUaNZin65kCA tools/python/xen/lowlevel/xu/domain_controller.h
40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/python/xen/lowlevel/xu/xu.c
41052eb84_irpx0E9N_kqBp9eoin5g tools/python/xen/sv/CreateDomain.py
+4107986egkTAMIHW7n-i4ShvCGWpLQ tools/python/xen/sv/Daemon.py
40fcefb2qm13BbRZBydAatOavaS0fQ tools/python/xen/sv/DomInfo.py
40fcefb2-RIU8GB67mJMRzybME9bxw tools/python/xen/sv/DomList.py
40fcefb23FfQn-ZBCbcHqA0cPGqQxw tools/python/xen/sv/GenTabbed.py
40fcefb2Sif__6AqrANeBQZZfvP-6w tools/python/xen/sv/TabView.py
41052eb8UrgtUkuJPg7oY1tutVQHsg tools/python/xen/sv/Wizzard.py
40fcefb2DqteqCCZYDCvvh4Q5jBd0w tools/python/xen/sv/__init__.py
+4107986e6qN1IdvIDdId0AYFmDMkiQ tools/python/xen/sv/params.py
40fcefb4rnaZNjqsBu7A5V2rlLyqRw tools/python/xen/sv/util.py
40d8915cyoVA0hJxiBFNymL7YvDaRg tools/python/xen/util/Brctl.py
40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/python/xen/util/__init__.py
tools/xfrd/xfrd
xen/tools/elf-reloc
xen/tools/figlet/figlet
+docs/interface.aux
+docs/interface.log
+docs/interface.pdf
+docs/interface.ps
+docs/interface.toc
+docs/user.aux
+docs/user.log
+docs/user.pdf
+docs/user.ps
+docs/user.toc
+tools/web-shutdown.tap
TARGETS = xen_cpuperf
INSTALL_BIN = $(TARGETS) xencons
-INSTALL_SBIN = netfix xm xend
+INSTALL_SBIN = netfix xm xend xensv
all: $(TARGETS)
$(MAKE) -C miniterm
--- /dev/null
+#!/usr/bin/env python
+# -*- mode: python; -*-
+#============================================================================
+# Copyright (C) 2004 Tom Wilkie <tw275@cl.cam.ac.uk>
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+#============================================================================
+
+"""SV web interface Lives in /usr/sbin.
+ Provides pretty HTML management interface.
+
+ Run:
+
+ sv start
+
+ The daemon is stopped with:
+
+ sv stop
+
+ The daemon will be accessible from http://localhost:8080/
+"""
+import os
+import sys
+import re
+
+from xen.xend.server.params import PID_FILE as XEND_PID_FILE
+
+class CheckError(ValueError):
+ pass
+
+def hline():
+ print >>sys.stderr, "*" * 70
+
+def msg(message):
+ print >>sys.stderr, "*" * 3, message
+
+def check_logging():
+ """Check python logging is installed and raise an error if not.
+ Logging is standard from Python 2.3 on.
+ """
+ try:
+ import logging
+ except ImportError:
+ hline()
+ msg("Python logging is not installed.")
+ msg("Use 'make install-logging' at the xen root to install.")
+ msg("")
+ msg("Alternatively download and install from")
+ msg("http://www.red-dove.com/python_logging.html")
+ hline()
+ raise CheckError("logging is not installed")
+
+def check_twisted_version():
+ """Check twisted is installed with a supported version and print a warning if not.
+ Raises an error if twisted is not installed.
+ """
+ # Supported twisted release and major version.
+ RELEASE = 1
+ MAJOR = 3
+ try:
+ from twisted.copyright import version
+ except ImportError:
+ hline()
+ msg("The Twisted framework is not installed.")
+ msg("Use 'make install-twisted' at the xen root to install.")
+ msg("")
+ msg("Alternatively download and install version %d.%d or higher" % (RELEASE, MAJOR))
+ msg("from http://www.twistedmatrix.com/products")
+ hline()
+ raise CheckError("twisted is not installed")
+
+
+ (release, major, minor) = version.split('.')
+ release = int(release)
+ major = int(major)
+ if release > RELEASE: return
+ if release == RELEASE and major >= MAJOR: return
+ hline()
+ msg("Warning: Twisted version not supported: %s" % version)
+ msg("Use Twisted version %d.%d.0 or higher" % (RELEASE, MAJOR))
+ hline()
+
+def check_xend():
+ """Check xend is running
+ """
+
+ if not os.path.isfile(XEND_PID_FILE) or not os.path.getsize(XEND_PID_FILE):
+ hline()
+ msg( "Warning: Xend has not been detected as running." )
+ msg( "Please start it immediately with: xend start " )
+ hline()
+ return 0
+
+ # Read the pid of the previous invocation and search active process list.
+ pid = open(XEND_PID_FILE, 'r').read()
+ lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
+ for line in lines:
+ if re.search('^ *' + pid + '.+xend', line):
+ return 1
+
+ hline()
+ msg( "Warning: Xend has not been detected as running." )
+ msg( "Please start it immediately with: xend start " )
+ hline()
+ return 0
+
+def main():
+ try:
+ check_logging()
+ check_twisted_version()
+ check_xend()
+ except CheckError:
+ sys.exit(1)
+
+ from xen.sv import Daemon
+
+ daemon = Daemon.instance()
+
+ if not sys.argv[1:]:
+ print 'usage: %s {start|stop|restart}' % sys.argv[0]
+ elif os.fork():
+ pid, status = os.wait()
+ return status >> 8
+ elif sys.argv[1] == 'start':
+ return daemon.start()
+ elif sys.argv[1] == 'stop':
+ return daemon.stop()
+ elif sys.argv[1] == 'restart':
+ return daemon.stop() or daemon.start()
+ else:
+ print 'not an option:', sys.argv[1]
+ return 1
+
+if __name__ == '__main__':
+ sys.exit(main())
def __init__( self, urlWriter ):
- feilds = [( 'name', 'Name')]
+ feilds = [( 'name', 'VM Name:'),
+ ( 'memory', 'RAM (Mb):' )]
- Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 1" )
+ Sheet.__init__( self, urlWriter, feilds, "Create New Domain", 0 )
class CreatePage1( Sheet ):
def __init__( self, urlWriter ):
- feilds = [( 'name', 'Name')]
+ feilds = [( 'kernel_type', 'Kernel Type:'),
+ ( 'kernel_location', 'Kernel location:')]
- Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 2" )
+ Sheet.__init__( self, urlWriter, feilds, "Setup Kernel Image", 1 )
class CreatePage2( Sheet ):
def __init__( self, urlWriter ):
- feilds = [( 'name', 'Name')]
+ feilds = [( 'vbd_dom0', 'Location of vbd:'),
+ ( 'vbd_dom0', 'Vitualised location:')]
- Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 3" )
+ Sheet.__init__( self, urlWriter, feilds, "Setup Virtual Block Devices", 2 )
class CreatePage3( Sheet ):
def __init__( self, urlWriter ):
- feilds = [( 'name', 'Name')]
+ feilds = [( 'vifs', 'Number of Vifs:')]
- Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 4" )
\ No newline at end of file
+ Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 4", 3 )
--- /dev/null
+###########################################################
+## XenSV Web Control Interface Daemon
+## Copyright (C) 2004, K A Fraser (University of Cambridge)
+## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
+## Copyright (C) 2004, Tom Wilkie <tw275@cam.ac.uk>
+###########################################################
+
+import os
+import os.path
+import sys
+import re
+
+from xen.sv.params import *
+
+from twisted.internet import reactor
+from twisted.web import static, server, script
+
+class Daemon:
+ """The xend daemon.
+ """
+ def __init__(self):
+ self.shutdown = 0
+ self.traceon = 0
+
+ def daemon_pids(self):
+ pids = []
+ pidex = '(?P<pid>\d+)'
+ pythonex = '(?P<python>\S*python\S*)'
+ cmdex = '(?P<cmd>.*)'
+ procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
+ xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
+ procs = os.popen('ps -e -o pid,args 2>/dev/null')
+ for proc in procs:
+ pm = procre.match(proc)
+ if not pm: continue
+ xm = xendre.match(pm.group('cmd'))
+ if not xm: continue
+ #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
+ pids.append(int(pm.group('pid')))
+ return pids
+
+ def new_cleanup(self, kill=0):
+ err = 0
+ pids = self.daemon_pids()
+ if kill:
+ for pid in pids:
+ print "Killing daemon pid=%d" % pid
+ os.kill(pid, signal.SIGHUP)
+ elif pids:
+ err = 1
+ print "Daemon already running: ", pids
+ return err
+
+ def cleanup(self, kill=False):
+ # No cleanup to do if PID_FILE is empty.
+ if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
+ return 0
+ # Read the pid of the previous invocation and search active process list.
+ pid = open(PID_FILE, 'r').read()
+ lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
+ for line in lines:
+ if re.search('^ *' + pid + '.+xensv', line):
+ if not kill:
+ print "Daemon is already running (pid %d)" % int(pid)
+ return 1
+ # Old daemon is still active: terminate it.
+ os.kill(int(pid), 1)
+ # Delete the stale PID_FILE.
+ os.remove(PID_FILE)
+ return 0
+
+ def start(self, trace=0):
+ if self.cleanup(kill=False):
+ return 1
+
+ # Fork -- parent writes PID_FILE and exits.
+ pid = os.fork()
+ if pid:
+ # Parent
+ pidfile = open(PID_FILE, 'w')
+ pidfile.write(str(pid))
+ pidfile.close()
+ return 0
+ # Child
+ self.run()
+ return 0
+
+ def stop(self):
+ return self.cleanup(kill=True)
+
+ def run(self):
+ root = static.File( SV_ROOT )
+ root.indexNames = [ 'Main.rpy' ]
+ root.processors = { '.rpy': script.ResourceScript }
+ reactor.listenTCP( SV_PORT, server.Site( root ) )
+ reactor.run()
+
+ def exit(self):
+ reactor.diconnectAll()
+ sys.exit(0)
+
+def instance():
+ global inst
+ try:
+ inst
+ except:
+ inst = Daemon()
+ return inst
request.write( '<html><head><title>Xen</title><link rel="stylesheet" type="text/css" href="inc/style.css" />' )
request.write( '<script src="inc/script.js"></script>' )
request.write( '</head><body>' )
+ request.write('<form method="post" action="%s">' % request.uri)
def write_BOTTOM( self, request ):
- request.write('<form method="post" action="%s">' % request.uri)
request.write('<input type="hidden" name="op" value="">')
request.write('</form>')
request.write( "</body></html>" )
from xen.sv.HTMLBase import HTMLBase
from xen.xend import sxp
+DEBUG = 1
+
class Wizzard( HTMLBase ):
def __init__( self, urlWriter, title, sheets ):
HTMLBase.__init__( self )
self.title = title
self.sheets = sheets
- self.currSheet = 0
self.urlWriter = urlWriter
def write_MENU( self, request ):
currSheet = getVar( 'sheet', request )
if not currSheet is None:
+ currSheet = int( currSheet )
+ else:
+ currSheet = 0
+
+ op = getVar( 'op', request )
- self.currSheet = int( currSheet )
+ if op == 'next':
+ currSheet += 1
+ elif op == 'prev':
+ currSheet -= 1
- self.sheets[ self.currSheet ]( self.urlWriter ).write_BODY( request )
+ self.sheets[ currSheet ]( self.urlWriter ).write_BODY( request )
request.write( "</td></tr><tr><td><table width='100%' border='0' cellspacing='0' cellpadding='0'><tr>" )
- request.write( "<td width='80%'></td><td width='20%' align='center'>" )
- request.write( "<p align='center'><img src='images/previous.png' onclick='doOp( \"prev\" )' onmouseover='update( \"wizText\", \"Previous\" )' onmouseout='update( \"wizText\", \" \" )'> " )
- request.write( "<img src='images/next.png' onclick='doOp( \"next\" )' onmouseover='update( \"wizText\", \"Next\" )' onmouseout='update( \"wizText\", \" \" )'></p>" )
- request.write( "<p align='center'><span id='wizText'></span></p></td></tr></table>" )
+ request.write( "<td width='80%'></td><td width='20%' align='center'><p align='center'>" )
+ if currSheet > 0:
+ request.write( "<img src='images/previous.png' onclick='doOp( \"prev\" )' onmouseover='update( \"wizText\", \"Previous\" )' onmouseout='update( \"wizText\", \" \" )'> " )
+ if currSheet < ( len( self.sheets ) - 1 ):
+ request.write( "<img src='images/next.png' onclick='doOp( \"next\" )' onmouseover='update( \"wizText\", \"Next\" )' onmouseout='update( \"wizText\", \" \" )'>" )
+ request.write( "</p><p align='center'><span id='wizText'></span></p></td></tr></table>" )
request.write( "</td></tr></table>" )
+ def op_next( self, request ):
+ pass
+
+ def op_prev( self, request ):
+ pass
+
class Sheet( HTMLBase ):
- def __init__( self, urlWriter, feilds, title ):
+ def __init__( self, urlWriter, feilds, title, location ):
HTMLBase.__init__( self )
self.urlWriter = urlWriter
self.feilds = feilds
self.title = title
+ self.location = location
+ self.passback = "()"
def parseForm( self, request ):
- return sxp.toString( request.args )
+ do_not_parse = [ 'mod', 'op', 'sheet' ]
+
+ passed_back = request.args
+
+ temp_passback = passed_back.get( "passback" )
+
+ if temp_passback is not None and len( temp_passback ) > 0:
+ temp_passback = temp_passback[ len( temp_passback )-1 ]
+ else:
+ temp_passback = "(passback )"
+
+ last_passback = ssxp2hash( string2sxp( temp_passback ) )
+
+ if DEBUG: print last_passback
+
+ try:
+ del passed_back[ 'passback' ]
+ except:
+ pass
+
+ for (key, value) in passed_back.items():
+ if key not in do_not_parse:
+ last_passback[ key ] = value[ len( value ) - 1 ]
+
+ self.passback = sxp2string( hash2sxp( last_passback ) ) #store the sxp
+
+ if DEBUG: print self.passback
+
+ return last_passback #return the hash
def write_BODY( self, request ):
+
request.write( "<p>%s</p>" % self.title )
- previous_values = request.args
+ previous_values = self.parseForm( request ) #get the hash for quick reference
for (feild, name) in self.feilds:
- value = sxp.child_value( previous_values, feild )
+ value = previous_values.get( feild )
if value is None:
value = ''
request.write( "<p>%s<input type='text' name='%s' value='%s'></p>" % (name, feild, value) )
-
- def op_next( self, request ):
- pass
- def op_prev( self, request ):
- pass
+ request.write( "<input type='hidden' name='passback' value=\"%s\"></p>" % self.passback )
+ request.write( "<input type='hidden' name='sheet' value='%s'></p>" % self.location )
+
--- /dev/null
+SV_PORT = 8080
+SV_ROOT = "/var/xen/sv/"
+PID_FILE = "/var/xen/sv.pid"
\ No newline at end of file
else:
sxphash[ child[0] ] = child[1]
- return sxphash
+ return sxphash
+
+def ssxp2hash( s ):
+ sxphash = {}
+
+ for i in s:
+ if isinstance( i, types.ListType ) and len( i ) > 1:
+ sxphash[ i[0] ] = i[1]
+
+ return sxphash
+
+def hash2sxp( h ):
+ hashsxp = []
+
+ for (key, item) in h.items():
+ hashsxp.append( [key, item] )
+
+ return hashsxp
+
+def string2sxp( string ):
+ pin = sxp.Parser()
+ pin.input( string )
+ return pin.get_val()
+
+def sxp2string( sexp ):
+ return sxp.to_string( sexp )
def sxp2prettystring( sxp ):
class tmp: